#ifndef __M_LOOP_H__
#define __M_LOOP_H__
#include <mutex>
#include <condition_variable>
#include <thread>
#include <functional>
#include <atomic>
#include "buffer.hpp"

enum class AsyncType
{
    ASYNC_SAFE,  // 安全状态，表示缓冲区满了就阻塞，避免资源耗尽的风险
    ASYNC_UNSAFE  // 不考虑资源耗尽，无限扩容，用于测试
};
class AsyncLooper
{
public:
    using Functor = std::function<void(Buffer& buffer)>;
    using ptr = std::shared_ptr<AsyncLooper>;
    AsyncLooper(const Functor& cb, AsyncType loop_type = AsyncType::ASYNC_SAFE) 
                :_stop(false), 
                _thread(std::thread(&AsyncLooper::threadEntry, this)),
                _looper_type(loop_type),
                _callback(cb)
    {}
    ~AsyncLooper() { stop(); }
    void stop()
    {
        _stop = true;  // 退出标志
        _cond_con.notify_all();  // 唤醒所有工作线程，退出
        _thread.join();
    }
    void push(const char *data, size_t len)
    {
        // 无限扩容，非安全 2.固定大小-生产缓冲区数据满了就阻塞
        std::unique_lock<std::mutex> lock(_mutex);
        // 条件变量控制，若缓冲区剩余空间大小小于数据长度，则可以添加数据, 安全状态的保证
        if (_looper_type == AsyncType::ASYNC_SAFE)
        _cond_pro.wait(lock, [&]()
                       { return _pro_buf.writeableSize() >= len; });

        // 能走下来条件满足了
        _pro_buf.push(data, len);
        // 唤醒消费者对缓冲区数据处理
        _cond_con.notify_all();
    }

private:
    void threadEntry()  // 线程入口函数
    {  
        while (1)
        {
            // 互斥设置生命周期，缓冲区交换完后解锁（不对数据处理保护，不然串行化了）
            {
                // 判断生产缓冲区有没有数据，有则交换，无则阻塞
                std::unique_lock<std::mutex> lock(_mutex);
                // 若当前是退出前被唤醒，或者有数据被唤醒，则返回真，继续向下运行，否则重新陷入休眠
                _cond_con.wait(lock, [&]()
                               { return _stop || !_pro_buf.empty(); });
                // 退出标志被设置，且缓冲区已无数据，再退出，否则可能会有数据没有处理
                if (_stop && _pro_buf.empty())
                {
                    break;
                }
                _con_buf.swap(_pro_buf);
                if (_looper_type == AsyncType::ASYNC_SAFE)
                // 唤醒消费者
                    _cond_pro.notify_all();
            }

            // 唤醒后处理数据
            _callback(_con_buf);
            // 初始化消费缓冲区
            _con_buf.reset();
        }
    }
private:
    Functor _callback;  //缓冲区数据处理执行的回调，由异步工作器使用者传入
private:
    std::atomic<bool> _stop;  // 停止标志
    Buffer _pro_buf;  // 生产
    Buffer _con_buf;  // 消费
    std::mutex _mutex;
    std::condition_variable _cond_pro;
    std::condition_variable _cond_con;
    std::thread _thread;  // 工作线程
    AsyncType _looper_type;  // 安全控制
};
#endif